/**
 * \file menu.c
 * \brief Routine controlant les modes
 * \author Nicolas M.
 * \version 0.2
 * \date 20 mars 2011
 * 
 * Programme de gestion du menu de la radio qui permet de piloter la radio et 
 * de basculer entre les différents modes existants. 
 *
 */
 
#include "menu.h"

#include "../utils/display.h"
#include "../utils/utils.h"

#include "mode_freq.h"
#include "mode_station.h"
#include "mode_vol.h"

#include <msp430x14x.h>

#include <includes.h>
#include <stdlib.h>
#include <string.h>

#define STATS_TASK 4

// Index du mode actuellement actif
int currentMode = MODE_FREQUENCE;
int currentFreqMode = MODE_STATION;

// Fonctions du mode actif
void (*b2Function)(void);
void (*b3Function)(void);

// Fonctions du mode de sélection de fréquence actif
void (*b2FMFunction)(void);
void (*b3FMFunction)(void);
char *(*getFMText)(void);

extern OS_EVENT *ButtonMbox;
extern OS_EVENT *StatsMbox;

// Buffer pour le stockage du message ecran
char menuTxtBuffer[33];

int run = 0;
/*
 * Genere le texte affiché à l'écran en fonction
 * du mode courant
 */
void updateMenuText()
{
	char *chaine, *txt;
	int index;
	chaine = menuTxtBuffer;

	*chaine = '\0';
	chaine = strcat(chaine, " ");

	txt = getFMText();
	chaine = strncat(chaine, txt, 15);

	chaine = strcat(chaine, "\n ");
	index = strlen(chaine) -1 ;

	txt = getVolText();
	chaine = strncat(chaine, txt, 15);

	// Affichage d'un curseur indiquant le mode courant
	if (currentMode == MODE_FREQUENCE)
		chaine[0] = '>';
	else
	{
		chaine[index] = '>';
	}

	afficher(chaine);
}

/*
 * Met à jour les pointeurs de fonctions selon le mode courant
 */
void updateMode()
{
	if (currentMode == MODE_FREQUENCE)
	{ 
		b2Function = *b2FMFunction;
		b3Function = *b3FMFunction;
	}
	else
	{
		b2Function = &volButton2fct;
		b3Function = &volButton3fct;
	}
}

/*
 * Met à jour les pointeurs de fonctions FM selon le mode
 * de selection de la frequence (manuel ou station)
 */
void updateFreqMode()
{
	if (currentFreqMode == MODE_STATION)
	{
		activateStationMode();
		b2FMFunction = &stationButton2fct;
		b3FMFunction = &stationButton3fct;
		getFMText = &getStationText;
		
		//OSMboxPost(StatsMbox, STATS_RESUME);
	}
	else
	{
		//OSMboxPost(StatsMbox, STATS_STOP);

		activateFreqMode();
		b2FMFunction = &freqButton2fct;
		b3FMFunction = &freqButton3fct;
		getFMText = &getFreqText;

	}
}

void quit()
{
	//OSMboxPost(StatsMbox, STATS_STOP);
	couperSon();
	saveMode(getMode());
	saveVolume(getVolume());
	saveFrequence(getFrequence());
	saveStation(getStationCourante());
	saveMemory();

}

/*
 * Lance la procedure d'enregistrement de la frequence
 * dans une des 5 zones mémoire réservée à l'utilisateur
 * La procedure comprend une étape de sélection de la station user.
 */
void enregistrerStationPerso()
{
	int done = 0, button, index = 1;
	INT8U err;
	char *chaine, *nb;
	while (!done)
	{
		chaine = menuTxtBuffer;
		sprintf(chaine,"USER $\n                ");

		chaine[1+7]= 0x17; // Symbole de retour
		chaine[5+7]= 0x9D; // Coeur
		chaine[9+7]= 0x18; // Fleche haut
		chaine[13+7]= 0x19; // Fleche bas
		nb = strstr(chaine,"$");
		*nb = index + '0';
		afficher(chaine);
		button = OSMboxPend(ButtonMbox, 0, &err);
		if (err == OS_NO_ERR)
		{
			switch (button)
			{
				// Annule l'enregistrement
				case COM_MENU:
				case COM_B1:
					done = 1;
					break;
				// Effectue l'engistrement
				case COM_PLAY:
				case COM_B2:
					saveStationPerso(index, getDac());
					restaurerUserStation(index, getDac());
					done = 1;
					break;
				// Passe a la station USER suivante
				case COM_NEXT:
				case COM_B3:
					index = index < 5 ? index+1 : 1;
					break;
				// Passe a la station USER précédente
				case COM_PREV:
				case COM_B4:
					index = index > 1 ? index-1 : 5;
					break;
			}
		}
	}
}

void hook()
{
	INT8U err;
	int button;
	static int mute=0;
	
	run = 1;
	// Initialisation des fonctions
	updateFreqMode();
	updateMode();

	updateMenuText();
	while (run)
	{
		button = OSMboxPend(ButtonMbox, 0, &err);
		if (err == OS_NO_ERR)
		{
			switch (button)
			{
				// Bascule en le mode volume et fréquence
				case COM_B1:
					currentMode = (currentMode == MODE_FREQUENCE) ? MODE_VOLUME : MODE_FREQUENCE;
					updateMode();
					break;
				// Bascule en le mode station et manuel pour la sélection de la fréquence
				case COM_B2:
					currentFreqMode = (currentFreqMode == MODE_STATION) ? MODE_MANUEL : MODE_STATION;
					updateFreqMode();
					updateMode();
					break;
				// Appel de la fonction du mode courant
				case COM_B3:
					b2Function();
					break;
				// Appel de la fonction du mode courant
				case COM_B4:
					b3Function();
					break;
				// Extinction de la radio (avec enregistrement du contexte)
				case COM_B1_LONG:
					run = 0;
					quit();
					break;
				// Enregistrement de la fréquence
				case COM_B2_LONG:
					if (currentFreqMode == MODE_MANUEL) enregistrerStationPerso();
					break;
				case COM_B3_LONG:
					// Nothing
					break;
				case COM_B4_LONG:
					//Nothing
					break;
				/* Commandes distantes */
				case COM_MORE:
					volButton2fct();
					break;
				case COM_LESS:
					volButton3fct();
					break;
				case COM_NEXT:
					b2FMFunction();
					break;
				case COM_PREV:
					b3FMFunction();
					break;
				case COM_PLAY:
					if(OSMboxPend(ButtonMbox, DELAY_100ms*2, &err))
					{
						run = 0;
						quit();
					}
					else
					{
						if (mute)
						{
							remettreSon();
							mute = 0;
						}
						else
						{
							couperSon();
							mute = 1;
						}
					}
					break;
				case COM_MENU:
					if(OSMboxPend(ButtonMbox, DELAY_100ms*2, &err))
					{
						if (currentFreqMode == MODE_MANUEL) enregistrerStationPerso();
					}
					else
					{
						currentFreqMode = (currentFreqMode == MODE_STATION) ? MODE_MANUEL : MODE_STATION;
						updateFreqMode();
						updateMode();
					}
					break;
			}
			updateMenuText();
		}
	}
}


void restaurerMode(unsigned int mode)
{
	if (mode & 1) currentFreqMode = MODE_MANUEL;
	if (mode & 2) currentMode = MODE_VOLUME;
}


unsigned int getMode()
{
	return 2*currentMode + currentFreqMode;
}

unsigned int getFMMode()
{
	return currentFreqMode;
}


unsigned int isMenuRunning()
{
	return run;
}